///////////////////////////////////////////////////////////////////////////////
// File:        server.h
// Author:      671643387@qq.com
// Description:
///////////////////////////////////////////////////////////////////////////////

#ifndef PIO_SERVER_H_
#define PIO_SERVER_H_

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif

#if defined(__LINUX__)
#include <pthread.h>
#endif

#if defined(__cplusplus)
extern "C"
{
#endif

///////////////////////////////////////////////////////////////////////////////

#if !defined(SOCKET_ERROR)
    #define SOCKET_ERROR            -1
#endif
#define SOCKET_ERROR_WOULDBLOCK -500

struct pio_connection;
struct pio_server;
struct pio_worker;

struct pio_server_statics
{
    const char*         address;
    short               port;
    int                 backlog;

    int                 id_gen;
    int                 conn_total;
    int                 conn_load;

    int                 worker;
};

struct pio_worker_statics
{
    int                 conn_load;
#if defined(__WINDOWS__)
    unsigned int        id;
#elif defined(__LINUX__)
    pthread_t           id;
#endif
};

///////////////////////////////////////////////////////////////////////////////

typedef struct pio_connection*(*connection_create_func)(void);
typedef void(*connection_free_func)(struct pio_connection*);
typedef void(*connection_event_func)(struct pio_connection*, void*);

///////////////////////////////////////////////////////////////////////////////

struct pio_server* pio_server_new(void);
int pio_server_open(struct pio_server*, const char*, short, int);
int pio_server_run(struct pio_server*);
void pio_server_stop(struct pio_server*);
void pio_server_free(struct pio_server*);
int pio_server_config_worker(struct pio_server*, int);
struct pio_worker* pio_server_get_worker(struct pio_server*, int);
void pio_server_get_statics(struct pio_server*, struct pio_server_statics*);

void pio_server_set_connection_create_fn(struct pio_server*, connection_create_func);
void pio_server_set_connection_free_fn(struct pio_server*, connection_free_func);
void pio_server_set_connection_establised_fn(struct pio_server*, connection_event_func, void*);
void pio_server_set_connection_read_fn(struct pio_server*, connection_event_func, void*);
void pio_server_set_connection_write_fn(struct pio_server*, connection_event_func, void*);
void pio_server_set_connection_close_fn(struct pio_server*, connection_event_func, void*);

///////////////////////////////////////////////////////////////////////////////

int pio_connectoon_size(void);
int pio_connection_get_id(struct pio_connection*);
int pio_connection_notify_write(struct pio_connection*);
int pio_connection_read(struct pio_connection*, char*, unsigned int, int);
int pio_connection_write(struct pio_connection*, const char*, unsigned int, int);
void pio_connection_close(struct pio_connection*);
void pio_connection_set_userdata(struct pio_connection*, void*);
void* pio_connection_get_userdata(struct pio_connection*);
void pio_connection_set_read_fn(struct pio_connection*, connection_event_func, void*);
void pio_connection_set_write_fn(struct pio_connection*, connection_event_func, void*);
void pio_connection_set_close_fn(struct pio_connection*, connection_event_func, void*);
struct pio_server* pio_connection_get_server(struct pio_connection*);

///////////////////////////////////////////////////////////////////////////////

void pio_worker_get_statics(struct pio_worker*, struct pio_worker_statics*);

///////////////////////////////////////////////////////////////////////////////

#if defined(__cplusplus)
}
#endif

#endif /* PIO_SERVER_H_ */
